package com.jalonjia.paste.service.impl;

import com.jalonjia.paste.dao.PasteDAO;
import com.jalonjia.paste.pojo.Paste;
import com.jalonjia.paste.service.PasteService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

/**
 * @author jalon
 */
@Slf4j
@Service("mysqlPasteService")
@ConditionalOnProperty(value = "paste.datasource", havingValue = "mysql")
public class MySqlPasteServiceImpl implements PasteService {
    private static PasteDAO pasteDAO;
    private static Paste delayPaste;

    @Autowired
    public MySqlPasteServiceImpl(PasteDAO pasteDAO) {
        MySqlPasteServiceImpl.pasteDAO = pasteDAO;
        new Thread(() -> {
            try {
                timeWaiter();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "delay-delete").start();

    }

    /**
     * 添加时通知 timeWaiter 更新数据 （如果更新了的话）
     *
     * @param paste paste
     */
    @Override
    public void add(Paste paste) {
        if (delayPaste == null || paste.compareTo(delayPaste) < 0) {
            synchronized (this) {
                delayPaste = paste;
                pasteDAO.add(paste);
                notifyAll();
            }
        } else {
            pasteDAO.add(paste);
        }
    }

    @Override
    public Paste getById(String id) {
        return pasteDAO.getById(id);
    }

    /**
     * 用一个线程维护过期时间最近的 delayPaste，即可对所有 Paste 进行定时删除
     */
    private synchronized void timeWaiter() throws InterruptedException {
        while (true) {
            delayPaste = pasteDAO.getByExpirationTime();
            if (delayPaste == null) wait();
            long timeout = delayPaste.getDelay(TimeUnit.MILLISECONDS);
            if (timeout > 0) {
                log.info("\033[34mWaiting to delete\033[0m ：{}", delayPaste);
                wait(timeout);
            }
            if (delayPaste.getDelay(TimeUnit.MILLISECONDS) < 0) {
                pasteDAO.delById(delayPaste.getId());
                log.info("\033[33mTimeout and deleted\033[0m : {}", delayPaste);
            }
        }
    }

}
